Skip to content

GML-1971 GML-2018 Fix chat history display issue and improve usage#20

Merged
chengbiao-jin merged 2 commits into
mainfrom
GML-1971-Chat-History
Nov 22, 2025
Merged

GML-1971 GML-2018 Fix chat history display issue and improve usage#20
chengbiao-jin merged 2 commits into
mainfrom
GML-1971-Chat-History

Conversation

@chengbiao-jin

@chengbiao-jin chengbiao-jin commented Nov 22, 2025

Copy link
Copy Markdown
Collaborator

PR Type

Enhancement, Bug fix


Description

  • Route using 'history' when relevant

  • Generate answers from conversation context

  • Cache TokenCalculator via factory

  • UI loads and sorts chat history


Diagram Walkthrough

flowchart LR
  UI["Chat UI"] -- "send question + convoId" --> Agent["Agent Entry"]
  Agent -- "route with conversation" --> Router["Router (functions | vectorstore | history)"]
  Router -- "history" --> History["History lookup"]
  Router -- "functions" --> Inquiry["Map to schema / functions"]
  Router -- "vectorstore" --> SupportAI["SupportAI retrieval"]
  History -- "conversation as context" --> Generator["Answer Generator"]
  Inquiry -- "results" --> Generator
  SupportAI -- "retrieved contexts" --> Generator
  TokenCalc["Cached TokenCalculator"] -- "reuse across services" --> Services["Embeddings / Retrievers / Generator"]
Loading

File Walkthrough

Relevant files
Enhancement
13 files
embedding_services.py
Switch to cached token calculator factory                               
+2/-2     
base_llm.py
Add 'history' option to router prompt                                       
+4/-2     
token_calculator.py
Introduce cached get_token_calculator factory                       
+27/-0   
agent.py
Include conversation in agent inputs and logs                       
+1/-1     
agent_generation.py
Use cached token calculator in generator                                 
+2/-2     
agent_graph.py
Add history lookup path and workflow wiring                           
+42/-15 
agent_router.py
Route with conversation context and typed parser                 
+4/-4     
ui.py
Return timestamps in conversation history payload               
+4/-2     
BaseRetriever.py
Use cached token calculator in retriever                                 
+2/-2     
SideMenu.tsx
Revamp conversation history: sort, expand, resume               
+297/-77
chatbot_response.txt
Prompt updates: score and select contexts                               
+4/-4     
chatbot_response.txt
Prompt updates: score and select contexts                               
+4/-4     
chatbot_response.txt
Prompt updates: score and select contexts                               
+4/-4     
Miscellaneous
1 files
tigergraph_embedding_store.py
Reduce verbosity by suppressing similarity logs                   
+1/-1     
Bug fix
1 files
ActionProvider.tsx
Load/render past messages; refresh list on send                   
+70/-11 
Configuration changes
1 files
.eslintrc.cjs
Add rule to disallow trailing spaces                                         
+1/-0     

@chengbiao-jin
chengbiao-jin merged commit 76bf1db into main Nov 22, 2025
1 check failed
@chengbiao-jin
chengbiao-jin deleted the GML-1971-Chat-History branch November 22, 2025 02:08
@tg-pr-agent

tg-pr-agent Bot commented Nov 22, 2025

Copy link
Copy Markdown

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
🧪 No relevant tests
🔒 Security concerns

Sensitive information exposure:
question_for_agent now logs both the question and the full conversation via debug_pii. Ensure debug/PII logging is disabled in production and sanitized as needed. Additionally, the UI stores full conversation messages in localStorage (selectedConversationData), which persists across sessions and could expose sensitive chat content on shared machines.

⚡ Recommended focus areas for review

Runtime Error

The code uses createClientMessage to preload chat history but it is neither imported nor provided via props, which will cause a reference error and break the chat UI initialization flow.

        return timeA - timeB; // Oldest first
      });

      const loadedMessages: any[] = [];

      sortedMessages.forEach((msg: any) => {
        if (msg.role === "user") {
          // Create user message
          const userMessage = createClientMessage(msg.content || "", {
            delay: 0,
          });
          loadedMessages.push(userMessage);
        } else if (msg.role === "system") {
          // Create bot message
          const botMessage = createChatBotMessage({
            content: msg.content || "",
            response_type: msg.response_type || "text",
            query_sources: msg.query_sources,
            answered_question: msg.answered_question,
          });
          loadedMessages.push(botMessage);
        }
      });

      // Set the loaded messages in the chat state
      if (loadedMessages.length > 0) {
        setState((prev: any) => ({
          ...prev,
          messages: loadedMessages,
        }));
      }
    } catch (error) {
      // Silently handle error parsing conversation data
    }
  }
}, [createChatBotMessage, createClientMessage, setState]);
Possible Issue

PydanticOutputParser[RouterResponse](...) may raise a TypeError if the class is not subscriptable; the prior non-generic usage PydanticOutputParser(...) is the standard pattern. Also, the function is annotated to return str but returns a parsed object with .datasource, which mismatches the annotation.

def __init__(self, llm_model, db_conn: TigerGraphConnection):
    self.llm = llm_model
    self.db_conn = db_conn

def route_question(self, question: str, conversation: list[dict[str, str]] = None) -> str:
    """Route a question to the appropriate datasource.

    Args:
        question (str): The question to route.

    Returns:
        str: The datasource to use for the question.
    """
    LogWriter.info(f"request_id={req_id_cv.get()} ENTRY route_question with {question}")
    v_types = self.db_conn.getVertexTypes()
    e_types = self.db_conn.getEdgeTypes()

    router_parser = PydanticOutputParser[RouterResponse](pydantic_object=RouterResponse)

    prompt = PromptTemplate(
        template=self.llm.route_response_prompt,
Routing Logic

When SupportAI is disabled or the router selects vectorstore, the fallback route goes to history_lookup instead of the previous inquiry/function path. This may degrade answers by preferring history over vectorstore in unsupported configurations.

source = step.route_question(state["question"], state["conversation"])
logger.debug_pii(
    f"request_id={req_id_cv.get()} Routing question to: {source}"
)
if self.supportai_enabled and source.datasource == "vectorstore":
    return "supportai_lookup"
elif source.datasource == "functions":
    return "inquiryai_lookup"
else:
    return "history_lookup"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant